package ynu.edu.controller;

import io.github.resilience4j.ratelimiter.annotation.RateLimiter;
import jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.*;
import ynu.edu.entity.User;
import ynu.edu.feign.ServiceProviderService;

import java.time.LocalDateTime;
import java.util.Map;

/**
 * 限流器测试控制器
 * 测试流量控制功能
 */
@RestController
@RequestMapping("/ratelimiter")
public class RateLimiterTestController {

    @Resource
    private ServiceProviderService serviceProviderService;

    /**
     * 自定义限流器测试 - 每2秒最多5个请求
     */
    @GetMapping("/customLimit/{userId}")
    @RateLimiter(name = "customRateLimiter", fallbackMethod = "customLimitFallback")
    public Map<String, Object> customLimit(@PathVariable("userId") Integer userId) {
        // 调用远程服务
        User user = serviceProviderService.GetUserById(userId);
        
        return Map.of(
                "rateLimiter", "customRateLimiter",
                "status", "SUCCESS",
                "data", user,
                "timestamp", LocalDateTime.now(),
                "message", "自定义限流器 - 请求通过",
                "config", "每2秒最多5个请求",
                "requestId", System.currentTimeMillis()
        );
    }

    /**
     * 自定义限流器的降级方法
     */
    public Map<String, Object> customLimitFallback(Integer userId, Exception ex) {
        return Map.of(
                "rateLimiter", "customRateLimiter",
                "status", "RATE_LIMITED",
                "userId", userId,
                "timestamp", LocalDateTime.now(),
                "error", ex.getMessage(),
                "message", "请求频率过高，触发限流保护",
                "suggestion", "请等待2秒后重试",
                "fallbackData", Map.of(
                        "userId", userId,
                        "userName", "限流降级用户",
                        "message", "服务繁忙，请稍后重试"
                )
        );
    }

    /**
     * 限流器A测试 - 每2秒最多5个请求
     */
    @GetMapping("/testA")
    @RateLimiter(name = "rateLimiterA", fallbackMethod = "rateLimiterAFallback")
    public Map<String, Object> testRateLimiterA() {
        // 调用远程服务获取所有用户
        Map<String, Object> users = serviceProviderService.getAllUsers();
        
        return Map.of(
                "rateLimiter", "rateLimiterA",
                "status", "SUCCESS",
                "data", users,
                "timestamp", LocalDateTime.now(),
                "message", "限流器A - 请求通过",
                "config", "每2秒最多5个请求"
        );
    }

    /**
     * 限流器A的降级方法
     */
    public Map<String, Object> rateLimiterAFallback(Exception ex) {
        return Map.of(
                "rateLimiter", "rateLimiterA",
                "status", "RATE_LIMITED",
                "timestamp", LocalDateTime.now(),
                "error", ex.getMessage(),
                "message", "限流器A - 请求被限制",
                "fallbackData", "系统繁忙，请稍后重试"
        );
    }

    /**
     * 限流器B测试 - 每2秒最多2个请求（更严格的限制）
     */
    @GetMapping("/testB/{userId}")
    @RateLimiter(name = "rateLimiterB", fallbackMethod = "rateLimiterBFallback")
    public Map<String, Object> testRateLimiterB(@PathVariable("userId") Integer userId) {
        // 调用远程服务
        User user = serviceProviderService.GetUserById(userId);
        
        return Map.of(
                "rateLimiter", "rateLimiterB",
                "status", "SUCCESS",
                "data", user,
                "timestamp", LocalDateTime.now(),
                "message", "限流器B - 请求通过（严格限制）",
                "config", "每2秒最多2个请求",
                "userId", userId
        );
    }

    /**
     * 限流器B的降级方法
     */
    public Map<String, Object> rateLimiterBFallback(Integer userId, Exception ex) {
        return Map.of(
                "rateLimiter", "rateLimiterB",
                "status", "RATE_LIMITED",
                "userId", userId,
                "timestamp", LocalDateTime.now(),
                "error", ex.getMessage(),
                "message", "限流器B - 请求被严格限制",
                "suggestion", "当前限制较严格，请等待更长时间后重试",
                "fallbackData", Map.of(
                        "userId", userId,
                        "userName", "严格限流降级用户",
                        "message", "服务处于高负载保护模式"
                )
        );
    }

    /**
     * 批量测试限流效果
     */
    @GetMapping("/batchTest/{requestCount}")
    public Map<String, Object> batchTestRateLimit(@PathVariable("requestCount") Integer requestCount) {
        java.util.List<Map<String, Object>> results = new java.util.ArrayList<>();
        int successCount = 0;
        int rateLimitedCount = 0;
        long startTime = System.currentTimeMillis();

        // 快速发送多个请求
        for (int i = 0; i < requestCount; i++) {
            try {
                Map<String, Object> result = customLimit(i + 1);
                results.add(Map.of("attempt", i + 1, "result", result));
                if ("SUCCESS".equals(result.get("status"))) {
                    successCount++;
                } else {
                    rateLimitedCount++;
                }
            } catch (Exception e) {
                results.add(Map.of("attempt", i + 1, "error", e.getMessage()));
                rateLimitedCount++;
            }
            
            // 每次请求间隔100ms
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }

        long endTime = System.currentTimeMillis();

        return Map.of(
                "testType", "限流器批量测试",
                "totalRequests", requestCount,
                "totalTime", (endTime - startTime) + "ms",
                "successCount", successCount,
                "rateLimitedCount", rateLimitedCount,
                "results", results,
                "rateLimiterConfig", Map.of(
                        "limitForPeriod", 5,
                        "refreshPeriod", "2s",
                        "timeoutDuration", "100ms"
                ),
                "explanation", "观察限流效果：每2秒最多5个请求通过，其余被限制"
        );
    }

    /**
     * （10）基于OpenFeign的流量控制接口 - 使用customRateLimiter（每2秒最多5个请求）
     */
    @GetMapping("/userService/{userId}")
    @RateLimiter(name = "customRateLimiter", fallbackMethod = "userServiceFallback")
    public Map<String, Object> userService(@PathVariable("userId") Integer userId) {
        // 基于OpenFeign的远程微服务调用
        User user = serviceProviderService.GetUserById(userId);
        System.out.println("限流器调用成功，返回用户: " + user.getUserName() + " from " + user.getPassWord());
        
        return Map.of(
                "rateLimiter", "customRateLimiter",
                "status", "SUCCESS",
                "data", user,
                "timestamp", LocalDateTime.now(),
                "message", "用户服务 - 正常执行",
                "threadName", Thread.currentThread().getName(),
                "config", Map.of(
                        "limitForPeriod", 5,
                        "limitRefreshPeriod", "2s",
                        "timeoutDuration", "100ms"
                )
        );
    }

    /**
     * 用户服务的降级方法 - 流量控制触发时执行
     */
    public Map<String, Object> userServiceFallback(Integer userId, Exception ex) {
        System.out.println("限流器降级触发: " + ex.getMessage() + "，用户ID: " + userId);
        
        return Map.of(
                "rateLimiter", "customRateLimiter",
                "status", "FALLBACK",
                "userId", userId,
                "timestamp", LocalDateTime.now(),
                "error", ex.getMessage(),
                "message", "用户服务 - 流量限制触发，请稍后重试",
                "reason", "请求频率过高，已达到每2秒5个请求的限制",
                "retryAfter", "请等待2秒后重试"
        );
    }

    /**
     * 获取所有用户的流量控制接口
     */
    @GetMapping("/allUsers")
    @RateLimiter(name = "customRateLimiter", fallbackMethod = "allUsersFallback")
    public Map<String, Object> getAllUsers() {
        // 基于OpenFeign的远程微服务调用
        Map<String, Object> users = serviceProviderService.getAllUsers();
        System.out.println("限流器调用成功，获取所有用户列表");
        
        return Map.of(
                "rateLimiter", "customRateLimiter",
                "status", "SUCCESS",
                "data", users,
                "timestamp", LocalDateTime.now(),
                "message", "获取用户列表 - 正常执行",
                "threadName", Thread.currentThread().getName()
        );
    }

    /**
     * 获取所有用户的降级方法
     */
    public Map<String, Object> allUsersFallback(Exception ex) {
        System.out.println("限流器降级触发: " + ex.getMessage());
        
        return Map.of(
                "rateLimiter", "customRateLimiter",
                "status", "FALLBACK",
                "timestamp", LocalDateTime.now(),
                "error", ex.getMessage(),
                "message", "获取用户列表 - 流量限制触发",
                "fallbackData", "用户列表暂时不可用，请稍后重试",
                "retryAfter", "请等待2秒后重试"
        );
    }

    /**
     * 创建用户的流量控制接口
     */
    @PostMapping("/createUser")
    @RateLimiter(name = "customRateLimiter", fallbackMethod = "createUserFallback")
    public Map<String, Object> createUser(@RequestBody User user) {
        // 基于OpenFeign的远程微服务调用
        Map<String, Object> result = serviceProviderService.createUser(user);
        System.out.println("限流器调用成功，创建用户: " + user.getUserName());
        
        return Map.of(
                "rateLimiter", "customRateLimiter",
                "status", "SUCCESS",
                "data", result,
                "timestamp", LocalDateTime.now(),
                "message", "创建用户 - 正常执行",
                "threadName", Thread.currentThread().getName()
        );
    }

    /**
     * 创建用户的降级方法
     */
    public Map<String, Object> createUserFallback(User user, Exception ex) {
        System.out.println("限流器降级触发: " + ex.getMessage() + "，用户: " + user.getUserName());
        
        return Map.of(
                "rateLimiter", "customRateLimiter",
                "status", "FALLBACK",
                "userData", user,
                "timestamp", LocalDateTime.now(),
                "error", ex.getMessage(),
                "message", "创建用户 - 流量限制触发，请求已记录",
                "fallbackAction", "用户创建请求已暂存，将稍后处理",
                "retryAfter", "请等待2秒后重试"
        );
    }

    /**
     * 快速请求测试接口 - 用于测试限流效果
     */
    @GetMapping("/quickTest/{requestCount}")
    public Map<String, Object> quickTest(@PathVariable("requestCount") Integer requestCount) {
        java.util.List<Map<String, Object>> results = new java.util.ArrayList<>();
        int successCount = 0;
        int limitedCount = 0;
        long startTime = System.currentTimeMillis();

        // 快速发送多个请求测试限流效果
        for (int i = 1; i <= requestCount; i++) {
            try {
                Map<String, Object> result = userService(i);
                if ("SUCCESS".equals(result.get("status"))) {
                    successCount++;
                } else {
                    limitedCount++;
                }
                results.add(result);
                
                // 稍作延迟避免请求过快
                Thread.sleep(200);
            } catch (Exception e) {
                limitedCount++;
                results.add(Map.of(
                        "requestId", i,
                        "status", "ERROR",
                        "error", e.getMessage(),
                        "timestamp", LocalDateTime.now()
                ));
            }
        }

        long endTime = System.currentTimeMillis();

        return Map.of(
                "testType", "限流器快速测试",
                "totalRequests", requestCount,
                "successCount", successCount,
                "limitedCount", limitedCount,
                "totalTime", (endTime - startTime) + "ms",
                "results", results,
                "rateLimiterConfig", Map.of(
                        "limitForPeriod", 5,
                        "limitRefreshPeriod", "2s",
                        "timeoutDuration", "100ms"
                ),
                "explanation", "观察限流效果：每2秒最多5个请求，超出部分会被限流"
        );
    }

    /**
     * 限流器状态查询接口
     */
    @GetMapping("/status")
    public Map<String, Object> getRateLimiterStatus() {
        return Map.of(
                "timestamp", LocalDateTime.now(),
                "rateLimiterInstances", Map.of(
                        "customRateLimiter", Map.of(
                                "limitForPeriod", 5,
                                "limitRefreshPeriod", "2s",
                                "timeoutDuration", "100ms",
                                "description", "自定义限流器 - 符合题目要求"
                        ),
                        "rateLimiterA", Map.of(
                                "limitForPeriod", 5,
                                "limitRefreshPeriod", "2s",
                                "timeoutDuration", "1000ms"
                        ),
                        "rateLimiterB", Map.of(
                                "limitForPeriod", 2,
                                "limitRefreshPeriod", "2s",
                                "timeoutDuration", "500ms"
                        )
                ),
                "testEndpoints", java.util.List.of(
                        "GET /ratelimiter/userService/{userId}",
                        "GET /ratelimiter/allUsers",
                        "POST /ratelimiter/createUser",
                        "GET /ratelimiter/quickTest/{count}"
                ),
                "flowControlFeatures", java.util.List.of(
                        "基于OpenFeign的远程调用流量控制",
                        "自定义刷新周期（2秒）",
                        "限制每周期最大请求数（5个）",
                        "流量限制时的服务降级",
                        "友好的错误提示和重试建议"
                )
        );
    }
} 